// ---------------------------------
// Global module
// ---------------------------------
const ADDON_CHANNEL = -1;
const HUB_CHANNEL = -2;

const debug = {
    relativeFile: false,
    logToTab: false,
    showHubTab: false
};

var tasks = {};
var channels = {}; // each channel has only one tab
// ---------------------------------
// Includes 
// ---------------------------------
var chrome = require('chrome');
var Cu = chrome.Cu;
Cu.import("resource://gre/modules/Services.jsm");
var buttons = require('sdk/ui/button/action');
var tabs = require("sdk/tabs");
var page_worker = require("sdk/page-worker");
var self = require("sdk/self");
var functionals = require("sdk/lang/functional");
var delay = functionals.delay;

// ---------------------------------
// Constants
// ---------------------------------
const blankPath = "./blank.txt";
const hubPath = "./hub.js";
const pageMessengerPath = "./pageMessenger.js"
const jQueryPath = self.data.url("jquery-2.1.4.js");
const testGrabPath = self.data.url("testGrab.js");



// ---------------------------------
// Work flow 
// ---------------------------------
var buttons = require("sdk/ui/button/action");

var button = buttons.ActionButton({
    id: "my-button1",
    label: "my button1",
    icon: "./icon-16.png",
    onClick: load
});
load();



// ----------------------------------
// Methods :
// ----------------------------------
function load()
{
    if (debug.showHubTab)
    {
        openTabWithScript(blankPath, hubPath, HUB_CHANNEL, "Hub");
    }
    else
    {
        openHiddenScript(blankPath, hubPath, HUB_CHANNEL, "Hub");
    }
}

function openHiddenScript(url, atttachedScripts, channel, name)
{

    var worker = page_worker.Page({
        contentURL: url,
        contentScriptFile: self.data.url("scriptLoader.js")
    });
    recordNewChannel(channel, worker, undefined, atttachedScripts);
    initWorker(worker, name, atttachedScripts);
}

function openTabWithMessenger(url, pageScript, channel, name)
{
    return openTabWithScript(url, [pageMessengerPath].concat(pageScript), channel, name);
}

function openTabWithScript(url, atttachedScripts, channel, name)
{
    var worker;
    tabs.open({
        url: url,
        onReady: onReady,
        onLoad: onLoaed,
        onClose: onClose
    });
    function onLoaed(tab)
    {
        tab.worker.port.emit("loaded");
    }
    function onReady(tab)
    {
        log("-------------------------------------------------------");
        log("New Tab : " + name);
        log("-------------------------------------------------------");
        var worker = tab.attach({
            contentScriptFile: [self.data.url("scriptLoader.js")]
        });
        recordNewChannel(channel, worker, tab, url);
        initWorker(worker, name, atttachedScripts);
        tab.activate();
    }
    function onClose(tab)
    {
        if (channels[tab.channel] && channels[tab.channel].tab === tab)
        {
            delete channels[tab.channel];
        }
        log("Tab closed (channel " + tab.channel + ")");
    }
    return;
}

// ---------------------------
// Sub Functions
// ---------------------------
function recordNewChannel(channel, worker, tab, url)
{
    if (channels[channel])
    {
        if (channels[channel].tab)
        {
            if(channels[channel].tab != tab)
                channels[channel].tab.close();
        }
        else if( channels[channel].worker)
        {
            if (channels[channel].worker != worker)
                channels[channel].worker.destroy();
        }
    }
    if (tab)
    {
        tab.channel = channel;
        tab.worker = worker;
    }
    worker.tab = tab;
    worker.channel = channel;
    channels[worker.channel] =
        {
            tab: tab,
            worker: worker,
            url: url
        }
}

function initWorker(worker, name, atttachedScripts)
{
    // Load script when script loader finished initialization.
    atttachedScripts = [].concat(atttachedScripts);
    worker.port.on("ScriptLoader::Initialized", loadPreloadScript);
    worker.port.on("ScriptLoader::PreloadScriptLoaded", loadPreloadScript);

    // Listening messages
    attachPageMessenger(worker);

    // Enable script loader
    enableScriptLoader(worker);

    // Set its name
    worker.port.emit("setScriptName", name);

    // Use initialized ScriptLoader to load the script needed to load
    function loadPreloadScript(index)
    {
        if (undefined === index)
            index = -1;
        if (++index < atttachedScripts.length)
        {
            worker.port.emit("ScriptLoader::LoadPreloadScript", atttachedScripts[index], index);
        }
    }
}

function enableScriptLoader(worker)
{
    // Listening on script loading request
    worker.port.on("ScriptLoader::LoadScriptHelp", onLoadScript);

    function onLoadScript(arg)
    {
        if (debug.relativeFile)
        {
            if (arg.url.search("./") === 0)
                arg.url = "file:///D:/WzhPrivate/Documents/QtProjects/TSearcher/TSeacherFirefox/data/" + arg.url;
        }

        // Create an page_worker to fetch the content of requestd script.
        var contentWorker = page_worker.Page({
            contentScript: "self.port.emit('ScriptContent', document.body.textContent)",
            contentURL: arg.url
        });

        // When content of requestd script is ready, send it back to worker who need our help to load script.
        contentWorker.port.on('ScriptContent', function (content)
        {
            worker.port.emit('ScriptLoader::onScriptContentLoaded', { url: arg.url, content: content, onFinished: arg.onFinished });
            contentWorker.destroy();
        });
    }
}

function attachPageMessenger(worker)
{
    // Hub work : listening message
    worker.port.on("msg", warpOnPageMessage);
    worker.port.on("log", onLogMessage);
    worker.port.on("hub", onHubMessage);
    worker.port.on("addon", warpOnMyMessage)

    function warpOnPageMessage(type, arg)
    {
        return onPageMessage(worker.channel, type, arg);
    }
    function warpOnMyMessage(type, arg)
    {
        return onMyMessage(worker.channel, type, arg);
    }
}

function onPageMessage(channel, type, arg)
{
    // All message from page script should be redirectd to TServer by hub
    channels[HUB_CHANNEL].worker.port.emit("hub", channel, type, arg);
}

function onHubMessage(channel, type, arg)
{
    if (tasks[type])
    {
        onMyMessage(channel, type, arg);
    }
    else
    {
        channels[channel].worker.port.emit("msg", type, arg);
    }
}

function onMyMessage(channel, type, arg)
{
    if (!tasks[type])
        log("<Error>[Add-on] : (channel " + channel + ")Task not exist : " + type);

    tasks[type](channel, arg);
}

function onLogMessage(msg)
{
    log(msg);
}

// --------------------------------
// Helper Functions
// --------------------------------

function log(arg)
{
    if (debug.logToTab && channels[HUB_CHANNEL]/*Tab is startuped*/)
        channels[HUB_CHANNEL].worker.port.emit("log", arg);
    else
        console.log(arg);
}


// ----------------------------------
// Tasks
// ----------------------------------

// reflect methods
tasks.closeMe = function (channel, arg)
{
    channels[channel].tab.close();
}

tasks.activateMe = function (channel, arg)
{
    channels[channel].tab.activate();
}

// startups
tasks.loadAccountInformation = function (newChannel, arg)
{
    openTabWithMessenger("https://www.baidu.com/",
        './basicInformation.js',
        newChannel, "Basic Information Fetcher");
}

tasks.searchTaobao = function (newChannel, arg)
{
    openTabWithMessenger("https://www.taobao.com/",
        './searchTaobao.js',
        newChannel, "Taobao Searcher");
}

tasks.searchTmall = function (newChannel, arg)
{
    openTabWithMessenger("https://www.tmall.com/",
        './searchTmall.js',
        newChannel, "Tmall Searcher");
}

tasks.searchTBcc = function (newChannel, arg)
{
    openTabWithMessenger("https://mosaic.re.taobao.com/search?keyword=" + arg.itemKeyword + "&_input_charset=utf-8",
        './searchTBcc.js',
        newChannel, "TBcc Searcher");
}

tasks.browseTaobao = function (newChannel, item)
{
    openTabWithMessenger(item.link,
        './browseTaobao.js',
        newChannel, "Taobao Browser");
}

tasks.searchSubItems = function (newChannel, arg)
{
    openTabWithMessenger(arg.link,
        './searchSubItems.js',
        newChannel, "Sub-Items Searcher");
}

tasks.browseShopIndex = function (newChannel, arg)
{
    openTabWithMessenger(arg.link,
        './browseShopIndex.js',
        newChannel, "Shop Index Browser");
}

tasks.clearCookies = function (newChannel, arg)
{
    Services.cookies.removeAll();
}

tasks.test = function (newChannel, arg)
{
    openTabWithMessenger("https://s.taobao.com/search?q=%E8%B6%B3%E7%90%83",
        './test.js',
        newChannel, "Test Task");
}